﻿package com.pandemicode.framework.utils {
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.GradientType;
	import flash.display.InterpolationMethod;
	import flash.display.SpreadMethod;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	/**
	* @author Michael Lawrence
	* @version 1.0.0
	*/
	public class Drawing {
		/**
		 * A series of helpful utilities for manipulating BitmapData.
		 */
		public function Drawing() { }
		
		/**
		 * Creates a BitmapData thumbnail of any DisplayObject.
		 * @param	o		The DisplayObject to create a thumbnail of.
		 * @param	width	The maximum width the thumbnail should occupy.
		 * @param	height	The maximum height the thumbnail should occupy.
		 * @return	Returns a BitmapData thumbnail of any DisplayObject.
		*/
		public static function thumbnail(o:DisplayObject, width:Number = 0, height:Number = 0):BitmapData {
			// Get the internal movieclip offset.
			var sr:Rectangle = o.getRect(o);
			var sm:Matrix = new Matrix();
			sm.translate( -sr.left, -sr.top);
			
			// Create the base bitmap data.
			var baseBMP:BitmapData = new BitmapData(sr.width, sr.height, true, 0x00000000);
			baseBMP.draw(o, sm);
			
			// Get bounds of non-transparent pixels.
			var r:Rectangle = baseBMP.getColorBoundsRect(0xffffffff, 0x00000000, false);
			
			// Get the scale of the thumbnail
			var p:Number = _scaleProportionately(new Point(sr.width, sr.height), width, height);
			
			baseBMP.dispose();
			
			// Create a matrix that is shifted to the correct position and scaled correctly.
			var m:Matrix = new Matrix();
			m.translate(-sr.left, -sr.top);
			m.translate(-r.left, -r.top);
			m.scale(p, p);
			
			// Now draw the bitmap data with the correct matrix.
			var bmp:BitmapData = new BitmapData(r.width * p, r.height * p, true, 0x00000000);
			bmp.draw(o, m);
			
			return bmp;
		}
		
		/**
		 * Scales the dimensions proportionately.
		 * @param	p	A Point that defines the width (x) and height (y) to scale.
		 * @param	w	The maximum width to scale to.
		 * @param	h	The maximum height to scale to.
		 * @return	Returns the percentage to scale the width and height to fit.
		 */
		private static function _scaleProportionately(p:Point, w:Number, h:Number):Number {
			var s:Number = 1.0;
			if (w > 0 && p.x > w)
				s = w / p.x;
			if (h > 0 && p.y * s > h)
				s = h / p.y;
			return s;
		}
		
		/**
		 * Draws a border around a BitmapData object.
		 * @param	b			The source BitmapData object.
		 * @param	color		The color of the border to draw.
		 * @param	thickness	The thickness of the border to draw.
		 */
		public static function drawBorder(b:BitmapData, color:uint = 0xff000000, thickness:Number = 1):void {
			b.fillRect(new Rectangle(0, 0, thickness, b.height), color);
			b.fillRect(new Rectangle(0, 0, b.width, thickness), color);
			b.fillRect(new Rectangle(b.width-thickness, 0, thickness, b.height), color);
			b.fillRect(new Rectangle(0, b.height-thickness, b.width, thickness), color);
		}
		
		/**
		 * Gets a bitmapData circle.
		 * @param	color	The color of the circle.
		 * @param	alpha	The alpha of the circle.
		 * @param	radius	The radius of the circle.
		 * @return	Returns a bitmapData circle.
		 */
		public static function getCircle(color:uint, alpha:Number, radius:Number):BitmapData {
			var s:Sprite = new Sprite();
			s.graphics.beginFill(color, alpha);
			s.graphics.drawCircle(radius/2, radius/2, radius);
			s.graphics.endFill();
			var c:BitmapData = new BitmapData(radius, radius, true, 0x00000000);
			c.draw(s, null, null, null, null, true);
			return c;
		}
		
		/**
		 * Gets a linear gradient as bitmapData.
		 * @param	size	The dimensions of the bitmapData.
		 * @param	colors	The colors in the gradient.
		 * @param	alphas	The alpha levels in the gradient.
		 * @param	ratios	The ratios in the gradient.
		 * @param	angle	The angle of the gradient.
		 * @return	Returns a linear gradient as bitmapData.
		 */
		public static function getLinearGradient(size:Point, colors:Array, alphas:Array, ratios:Array, angle:Number = 0):BitmapData {
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(size.x, size.y, MathEx.degreesToRadians(angle), 0, 0);
			
			var s:Sprite = new Sprite();
			s.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
			s.graphics.moveTo(0, 0);
			s.graphics.lineTo(size.x, 0);
			s.graphics.lineTo(size.x, size.y);
			s.graphics.lineTo(0, size.y);
			s.graphics.lineTo(0, 0);
			s.graphics.endFill();
			
			var bmp:BitmapData = new BitmapData(size.x, size.y, true, 0x00000000);
			bmp.draw(s);
			return bmp;
		}
	}
}